// Copyright (c) 2008, 
// Marc Speck, http://www.faindu.com
// All Rights Reserved. The following is Source Code and is subject to all restrictions 
// on such code as contained in the license accompanying this product.
package com.faindu.editImage.base
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.geom.Matrix;
import flash.net.URLRequest;
import flash.system.LoaderContext;

import mx.core.FlexSprite;
import mx.core.UIComponent;

/**
 * Dispatched when the image is successfully loaded and attached to the display list.
 *
 * @eventType com.faindu.editImage.ImageLoader.EVENT_IMAGE_ADDED
 */
[Event(name="imageAddedEvent", type="flash.events.Event")]

/**
 * Load an image as soon as the url is set.
 */
public class ImageLoader extends UIComponent implements IImageLoader
{
    //-------------------------------------------------------------------------- 
    //
    //  Constants
    //
    //--------------------------------------------------------------------------  
	/**
	 * The maximum number of pixels for the width of the image.
	 */
	public static const MAX_WIDTH:uint = 2880

	/**
	 * The maximum number of pixels for the heigth of the image.
	 */
	public static const MAX_HEIGHT:uint = 2880

	/**
	 * Event name when the image is attached to an instance of <code>ImageLoader</code>.
	 */
	 
    /**
     *  The <code>ImageLoader.EVENT_IMAGE_ADDED</code> constant defines the value of the
     *  <code>type</code> property of the event object for a <code>imageAddedEvent</code> event.
     * 
     *  //todo: update
     *  <p>The properties of the event object have the following values:</p>
     *  <table class="innertable">
     *     <tr><th>Property</th><th>Value</th></tr>
     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
     *     <tr><td><code>currentTarget</code></td><td>The control of a tool that defines the
     *       event listener that handles the event. The control normaly extends  
     *       <code>BaseControl</code> and is for example <code>ScaleControl</code>.</td></tr>
     *     <tr><td><code>target</code></td><td>The Object that dispatched the event;
     *       it is not always the Object listening for the event.
     *       Use the <code>currentTarget</code> property to always access the
     *       Object listening for the event.</td></tr>
     *     <tr><td><code>shiftKey</code></td><td>Whether the Shift key is down.</td></tr>
     *  </table>
     * 
     *  @eventType com.faindu.editImage.ImageLoader.EVENT_IMAGE_ADDED
     */	 
	public static const EVENT_IMAGE_ADDED: String = "com.faindu.editImage.ImageLoader.imageAddedEvent"

    //-------------------------------------------------------------------------- 
    //
    //  Variables
    //
    //--------------------------------------------------------------------------  
	/**
	 * @private 
	 * <code>loader</code> loads the bitmapData from the <code>url</code>.
	 * 
	 * @see #url
	 */
	protected var loader: Loader = new Loader()

	/** @private */	 
	protected var _image: Bitmap
	/**
	 * This is the bitmap of the image. Bitmap also allows access
	 * to the original <code>BitmapData</code>.
	 */
	public function get image(): Bitmap
	{
		return _image
	}
	
	/** @private */	
	protected var _imageHolder: FlexSprite = new FlexSprite()
	/**
	 * @private
	 * 
	 * This holds the image bitmap and all transformations are applied 
	 * to this Sprite.
	 */
	public function get imageHolder(): FlexSprite
	{
		return _imageHolder
	}

	public function set imageHolder( value:FlexSprite ): void
	{
		_imageHolder = value
	}
	
    //-------------------------------------------------------------------------- 
    //
    //  Properties
    //
    //--------------------------------------------------------------------------  	
	protected var _url: String
	/**
	 * @inheritDoc
	 * 
	 * @example Either http/https:  
	 * <listing version="3.0" >http://www.example.com/myimage.jpg</listing>
	 * @example or the file protocoll can be used:
	 * <listing version="3.0" >file://C:/devl/myimage.png</listing>
	 * 
	 * @see #showBitmap
	 */
	public function get url(): String
	{
		return _url
	}
	public function set url( value:String ): void
	{
		_url = value
		loader.contentLoaderInfo.addEventListener( Event.COMPLETE, loadingCompleteHandler )
		
		var loaderContext: LoaderContext = new LoaderContext()
		loaderContext.checkPolicyFile = true
		
		loader.load( new URLRequest( _url ), loaderContext )
	}

    //-------------------------------------------------------------------------- 
    //
    //  Methods
    //
    //--------------------------------------------------------------------------  		
	/**
	 * If the image is bigger than the max, it gets automatically scaled.
	 */
	protected function loadingCompleteHandler( event:Event ): void
	{
		var bitmap: Bitmap = Bitmap( event.currentTarget.content )
		showBitmap( bitmap )
	}
	
	/**
	 * @inheritDoc
	 * 
	 * @see #url
	 */
	public function showBitmap( bitmap:Bitmap, url:String=null ): void
	{
		if ( url )
		{
			_url = url
		}
		
		var bitmapData: BitmapData = bitmap.bitmapData
 			
		var originalWidth: Number = bitmapData.width
		var originalHeight: Number = bitmapData.height
		 
		// scale down the image if it is bigger than allowed Flash Player limits
		if ( originalWidth > MAX_WIDTH || originalHeight > MAX_HEIGHT)
		{
			var newWidth: Number = originalWidth
			var newHeight: Number = originalHeight
			var scaleX:Number = MAX_WIDTH / originalWidth
			var scaleY:Number = MAX_HEIGHT / originalHeight
			
			var scale:Number = Math.min( scaleX, scaleY )
			newWidth = originalWidth * scale
			newHeight = originalHeight * scale
	 		var matrix:Matrix = new Matrix()
			matrix.scale( scale, scale ) 
			
			var resizedBitmapData: BitmapData = new BitmapData( newWidth, newHeight, false, 0x00ff00 )
			resizedBitmapData.draw( bitmapData, matrix )
			_image = new Bitmap( resizedBitmapData )
		}
		else
		{
			_image = bitmap
		}

		_image.smoothing = true
		_imageHolder.addChildAt( _image, 0 )
		addChild( _imageHolder )
		
		invalidateSize()
		dispatchEvent( new Event( EVENT_IMAGE_ADDED ) )
	}
	
	/**
	 * @private
	 */
	override protected function measure():void
	{
		super.measure()
		
		if ( _image )
		{
			// don't use _image.width because it might be scaled.
			measuredWidth = _image.bitmapData.width
            measuredHeight = _image.bitmapData.height
		}
		else
		{
			measuredWidth = 10
			measuredHeight = 10
		}
	}
}
}